package gov.dhs.cis.soa.readers;

import gov.dhs.cis.soa.SOAData;
import gov.dhs.cis.soa.Utils;
import gov.dhs.cis.soa.Constants.EntityType;
import gov.dhs.cis.soa.data.Actor;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;


public class ActorsLayerReader extends ExcelReader {
	static final Logger loger = Logger.getLogger(ActorsLayerReader.class);

	private final String ACT_FILE_NAME = "Roles Catalog - 09272010 - Master-DRAFT.xls";	//"Roles Catalog - 07292010 - Master-DRAFT.xls";
	String ROLE_COL_NUM = "A";
	String DESC_COL_NUM = "B";
	String KINDOF_COL_NUM = "C";
	String BOOL_ACT_COL_NUM = "D";
	String PERSONA_COL_NAME = "F";
	String STATUS_ACT_COL_NUM = "I";
	int MAX_ACTS = 95;
	int MAX_PERSONA	= 8;
	
	public SOAData extractActors(SOAData soaData) {
		String[] ACT_SHEET_NAMES = { "Human Roles - Definitions", "External System Roles - Def." };
		String[] ACT_TYPES = { Actor.HUMAN_ROLE_TYPE, Actor.SYSTEM_ROLE_TYPE };
		
		String PERSONA_SHEET_NAME = "Persona Groups - Definitions";
		
		loger.debug("Extracting Actors layer Sheet...");
		List<Actor> actorsList = new ArrayList<Actor>();
		soaData.actorList = actorsList;
		
		//now load Persona groups.. - Rajesh Singh 08/02/2010
		HSSFWorkbook w = openFile(ACT_FILE_NAME);
		HSSFSheet s1 = w.getSheet(PERSONA_SHEET_NAME);
		int rows = s1.getLastRowNum();
		loger.debug("Persona rows =" + rows);
	
		for (int n = 1; n < MAX_PERSONA; n++) {
			HSSFRow row = s1.getRow(n);
			if(row == null)
				continue;
			Actor actor = new Actor();
			actor.id = Utils.getNextId();
			actor.name = getCellStringValue(w, row, ROLE_COL_NUM).trim();
			actor.desc = Utils.prepareDescObj(getCellStringValue(w, row, DESC_COL_NUM), EntityType.ACTR);
			actor.roleType = Actor.PERSONA_ROLE_TYPE;
			actorsList.add(actor);
		}

		w = openFile(ACT_FILE_NAME);
		for(int sheetNum = 0; sheetNum < ACT_SHEET_NAMES.length; sheetNum++) {
			String sheetName = ACT_SHEET_NAMES[sheetNum];
			s1 = w.getSheet(sheetName);
			rows = s1.getLastRowNum();
			loger.debug("Act rows =" + rows);
	
			for (int n = 1; n < MAX_ACTS; n++) {
				HSSFRow row = s1.getRow(n);
				if(row == null)
					continue;
				String data = getCellStringValue(w, row, STATUS_ACT_COL_NUM);
				if(!Utils.isEmpty(data) && "obsolete".equalsIgnoreCase(data))
					continue;
				data = getCellStringValue(w, row, KINDOF_COL_NUM);
				if(Utils.isEmpty(data))
					continue;
				String parentNames[] = data.split("[,;]");
				for(String parentName : parentNames) {
					Actor foundParent = Utils.findActorByName(parentName.trim(), actorsList);
					if(foundParent != null)
						continue;
					Actor parent = new Actor();
					parent.id = Utils.getNextId();				
					parent.name = parentName.trim();
					parent.roleType = ACT_TYPES[sheetNum];
					actorsList.add(parent);
				}
			}
			for (int n = 1; n < MAX_ACTS; n++) {
				HSSFRow row = s1.getRow(n);
				if(row == null)
					continue;
				String data = getCellStringValue(w, row, STATUS_ACT_COL_NUM);
				if(!Utils.isEmpty(data) && "obsolete".equalsIgnoreCase(data))
					continue;
				data = getCellStringValue(w, row, ROLE_COL_NUM);
				if(Utils.isEmpty(data))
					continue;
				data = data.trim();
				Actor foundAct = Utils.findActorByName(data, actorsList);
				if(foundAct != null) {
					//foundAct.id = Utils.getNextId();
					foundAct.desc = Utils.prepareDescObj(getCellStringValue(w, row, DESC_COL_NUM), EntityType.ACTR);
					foundAct.persona = Utils.findActorByName(getCellStringValue(w, row, PERSONA_COL_NAME), actorsList);
					foundAct.isActor = getCellStringValue(w, row, BOOL_ACT_COL_NUM);
				} else {
					Actor actor = new Actor();
					actor.id = Utils.getNextId();
					actor.name = getCellStringValue(w, row, ROLE_COL_NUM).trim();
					actor.desc = Utils.prepareDescObj(getCellStringValue(w, row, DESC_COL_NUM), EntityType.ACTR);
					actor.isActor = getCellStringValue(w, row, BOOL_ACT_COL_NUM);
					actor.roleType = ACT_TYPES[sheetNum];
					actor.persona = Utils.findActorByName(getCellStringValue(w, row, PERSONA_COL_NAME), actorsList);;
					actorsList.add(actor);
					String parentStr = getCellStringValue(w, row, KINDOF_COL_NUM);
					if(!Utils.isEmpty(parentStr)) {
						String parentNames[] = parentStr.split("[,;]");
						for(String parentName : parentNames) {
							parentName = parentName.trim();
							Actor foundParent = Utils.findActorByName(parentName, actorsList);
							if(foundParent != null) {
								foundParent.addChildActor(actor);
							} else {
								loger.error(actor.name + " - No parent found!!!! - " + parentName);
							}
						}
					}
				}
			}
		}
		
		//traverse and list all the unable to found records.
		for (Actor actor : actorsList) {
			if(actor.id == 0 && !Utils.isEmpty(actor.name))
				loger.error("Wrong Actor found for : <<" + actor.name + ">>");
			if(actor.childrenList == null)
				continue;
			for(Actor a : actor.childrenList) {
				if(a.id == 0 && !Utils.isEmpty(a.name)) {
					loger.error("No Parent Actor found for : <<" + actor.name + ">>");
				}
			}
		}
		
		closeAll(w);
		return soaData;
	}

	public List<Actor> extractActors_working() {
		String ACT_SHEET_NAME = "Human Roles";
		
		loger.debug("Extracting Actors layer Sheet...");
		HSSFWorkbook w = openFile(ACT_FILE_NAME);
		HSSFSheet s1 = w.getSheet(ACT_SHEET_NAME);
		int rows = s1.getLastRowNum();
		loger.debug("Act rows =" + rows);

		List<Actor> actorsList = new ArrayList<Actor>();
		for (int n = 1; n < MAX_ACTS; n++) {
			HSSFRow row = s1.getRow(n);
			if(row == null)
				continue;
			Actor actor = new Actor();
			String data = getCellStringValue(w, row, ROLE_COL_NUM);
			if(Utils.isEmpty(data))
				continue;
			data = getCellStringValue(w, row, KINDOF_COL_NUM);
			if(Utils.isEmpty(data)) {
				actor.childrenList = null;
			} else {
				String parentNames[] = data.split("\\,");
				for(String parentName : parentNames) {
					Actor parent = new Actor();
					parent.id = 0;				
					parent.name = parentName.trim();
					actor.addChildActor(parent);
				}
				/*
				Actor foundActor = findActor(actorsList, w, s1, data);
				if(foundActor != null) {
					actor.parent.id = foundActor.id;				
					actor.parent.name = data;
				} else {
					loger.debug("Couldnt found parent Role <<" + data + ">>");
				}
				*/
			}
			actor.id = Utils.getNextId();
			actor.name = getCellStringValue(w, row, ROLE_COL_NUM).trim();
			actor.desc = Utils.prepareDescObj(getCellStringValue(w, row, DESC_COL_NUM), EntityType.ACTR);
			actorsList.add(actor);
		}
		
		List<Actor> needs2Reconsile = new ArrayList<Actor>();
		for (Actor actor : actorsList) {
			if(actor.childrenList == null)
				continue;
			Actor parent = null;
			for(int i = actor.childrenList.size()-1; i >= 0; i--) {
				parent = actor.childrenList.get(i);
				Actor foundAct = Utils.findActorByName(parent.name, actorsList);
				if(foundAct == null)
					foundAct = Utils.findActorByName(parent.name, needs2Reconsile);
				if(foundAct != null)
					actor.childrenList.set(i, foundAct);
				else {
					loger.debug("Adding Parent Actor since it is not found in the list, Parent: <<" + parent.name + ">>");
					parent.id = Utils.getNextId();
					parent.desc = Utils.prepareDescObj("Non Existing Parent", EntityType.ACTR);
					needs2Reconsile.add(parent);
				}
			}
		}
		for(Actor actor : needs2Reconsile)
			actorsList.add(actor);
		
		//traverse and list all the unable to found records.
		for (Actor actor : actorsList) {
			if(actor.childrenList == null)
				continue;
			for(Actor a : actor.childrenList) {
				if(a.id == 0 && !Utils.isEmpty(a.name)) {
					loger.debug("No Parent Actor found for : <<" + actor.name + ">>");
				}
			}
		}
		
		closeAll(w);
		return actorsList;
	}
	
	private Actor findActor(List<Actor> list, HSSFWorkbook w, HSSFSheet s1, String actNam) {
		if(Utils.isEmpty(actNam))
			return null;	//to skip to get persist
		Actor foundO = Utils.findActorByName(actNam, list);
		if(foundO != null)
			return foundO;
		Actor actor = new Actor();
		for (int n = 1; n < MAX_ACTS; n++) {
			HSSFRow row = s1.getRow(n);
			if(row == null)
				continue;
			actor.name = getCellStringValue(w, row, ROLE_COL_NUM);
			if(actNam.equalsIgnoreCase(actor.name)) {
				actor.id = Utils.getNextId();
				actor.name = getCellStringValue(w, row, ROLE_COL_NUM);
				actor.desc = Utils.prepareDescObj(getCellStringValue(w, row, DESC_COL_NUM), EntityType.ACTR);
				String parent = getCellStringValue(w, row, KINDOF_COL_NUM);
				if(!Utils.isEmpty(parent)) {
					Actor parentActor = findActor(list, w, s1, parent);
					if(parentActor != null) {
						actor.addChildActor(parentActor);
					}
				}
				list.add(actor);
				return actor;
			}
		}
		return null;
	}
}
